package com.warom.sdg.util;

import android.os.Handler;
import android.os.Looper;
import android.util.Log;

import com.warom.sdg.callback.PlcDataListener;

/**
 * Modbus RTU通信帮助类
 * 提供常用的Modbus RTU通信操作示例
 */
public class ModbusRtuHelper {
    private static final String TAG = "ModbusRtuHelper";
    
    // Modbus地址范围定义
    public static final int COIL_START = 1;             // 00001
    public static final int COIL_END = 9999;            // 09999
    public static final int DISCRETE_INPUT_START = 10001;
    public static final int DISCRETE_INPUT_END = 19999;
    public static final int INPUT_REGISTER_START = 30001;
    public static final int INPUT_REGISTER_END = 39999;
    public static final int HOLDING_REGISTER_START = 40001;
    public static final int HOLDING_REGISTER_END = 49999;
    
    private ModbusRtuClient modbusRtuClient;
    private PlcDataListener dataListener;
    
    /**
     * 构造函数
     * @param serialPortPath 串口路径
     * @param baudRate 波特率
     * @param listener 数据监听器
     */
    public ModbusRtuHelper(String serialPortPath, int baudRate, PlcDataListener listener) {
        modbusRtuClient = new ModbusRtuClient(serialPortPath, baudRate, listener);
        this.dataListener = listener;
    }
    
    /**
     * 设置串口参数
     * @param dataBits 数据位 (5-8)
     * @param stopBits 停止位 (1-2)
     * @param parity 校验位 (0:无校验, 1:奇校验, 2:偶校验)
     */
    public void setSerialPortParams(int dataBits, int stopBits, int parity) {
        modbusRtuClient.setSerialPortParams(dataBits, stopBits, parity);
    }
    
    /**
     * 设置超时时间
     * @param timeout 超时时间（毫秒）
     */
    public void setTimeout(int timeout) {
        modbusRtuClient.setTimeout(timeout);
    }
    
    /**
     * 设置Modbus设备ID
     * @param unitId 设备ID (1-247)
     */
    public void setUnitId(int unitId) {
        modbusRtuClient.setUnitId(unitId);
    }
    
    /**
     * 检查连接状态
     * @return 是否已连接
     */
    public boolean isConnected() {
        return modbusRtuClient != null && modbusRtuClient.isConnected();
    }
    
    /**
     * 连接到设备
     * @return 是否连接成功
     */
    public boolean connect() {
        return modbusRtuClient.connect();
    }
    
    /**
     * 断开与设备的连接
     */
    public void disconnect() {
        modbusRtuClient.disconnect();
    }
    
    /**
     * 异步连接到PLC设备
     */
    public void connectAsync() {
        connectAsync(null);
    }
    
    /**
     * 异步连接到PLC设备，完成后执行指定的回调
     * @param callback 连接完成后要执行的回调，可以为null
     */
    public void connectAsync(final Runnable callback) {
        new Thread(() -> {
            final boolean result = modbusRtuClient.connect();
            
            // 在主线程上执行回调
            new Handler(Looper.getMainLooper()).post(() -> {
                if (!result && dataListener != null) {
                    dataListener.onError("连接串口设备失败");
                }
                
                if (callback != null) {
                    callback.run();
                }
            });
        }).start();
    }
    
    /**
     * 读取PLC线圈状态
     * @param address 起始地址 (0-65535)
     * @param count 读取数量
     * @param unitId 设备单元ID
     */
    public void readCoils(final int address, final int count, final int unitId) {
        if (!isConnected()) {
            if (dataListener != null) {
                dataListener.onError("未连接到串口设备");
            }
            return;
        }
        
        // 设置设备ID
        modbusRtuClient.setUnitId(unitId);
        
        // 读取线圈状态
        modbusRtuClient.readCoils(address, count);
    }
    
    /**
     * 读取PLC离散输入状态
     * @param address 起始地址 (0-65535)
     * @param count 读取数量
     * @param unitId 设备单元ID
     */
    public void readDiscreteInputs(final int address, final int count, final int unitId) {
        if (!isConnected()) {
            if (dataListener != null) {
                dataListener.onError("未连接到串口设备");
            }
            return;
        }
        
        // 设置设备ID
        modbusRtuClient.setUnitId(unitId);
        
        // 读取离散输入状态
        modbusRtuClient.readDiscreteInputs(address, count);
    }
    
    /**
     * 读取PLC寄存器
     * @param address 起始地址
     * @param count 寄存器数量
     * @param unitId 设备单元ID
     * @param isInputRegister 是否为输入寄存器，false为保持寄存器
     */
    public void readRegisters(final int address, final int count, final int unitId, final boolean isInputRegister) {
        if (!isConnected()) {
            if (dataListener != null) {
                dataListener.onError("未连接到串口设备");
            }
            return;
        }
        
        // 设置设备ID
        modbusRtuClient.setUnitId(unitId);
        
        // 读取寄存器
        if (isInputRegister) {
            modbusRtuClient.readInputRegisters(address, count);
        } else {
            modbusRtuClient.readHoldingRegisters(address, count);
        }
    }
    
    /**
     * 写入单个线圈
     * @param address 地址
     * @param value 值
     * @param unitId 设备单元ID
     * @return 是否写入成功
     */
    public boolean writeSingleCoil(final int address, final boolean value, final int unitId) {
        if (!isConnected()) {
            if (dataListener != null) {
                dataListener.onError("未连接到串口设备");
            }
            return false;
        }
        
        // 设置设备ID
        modbusRtuClient.setUnitId(unitId);
        
        // 写入线圈状态
        modbusRtuClient.writeSingleCoil(address, value);
        return true;
    }
    
    /**
     * 写入单个寄存器
     * @param address 地址
     * @param value 值
     * @param unitId 设备单元ID
     * @return 是否写入成功
     */
    public boolean writeSingleRegister(final int address, final int value, final int unitId) {
        if (!isConnected()) {
            if (dataListener != null) {
                dataListener.onError("未连接到串口设备");
            }
            return false;
        }
        
        // 设置设备ID
        modbusRtuClient.setUnitId(unitId);
        
        // 写入寄存器值
        modbusRtuClient.writeSingleRegister(address, value);
        return true;
    }
    
    /**
     * 根据地址字符串读取数据
     * 支持格式：
     * - 线圈: 00001-09999
     * - 离散输入: 10001-19999
     * - 输入寄存器: 30001-39999
     * - 保持寄存器: 40001-49999
     * @param addressStr 地址字符串
     * @param count 读取数量
     * @param unitId 设备单元ID
     * @return 是否读取成功
     */
    public boolean readAddress(String addressStr, int count, int unitId) {
        ModbusAddressInfo addressInfo = parseModbusAddress(addressStr);
        
        if (addressInfo == null) {
            if (dataListener != null) {
                dataListener.onError("无效的Modbus地址: " + addressStr);
            }
            return false;
        }
        
        try {
            switch (addressInfo.type) {
                case COIL:
                    readCoils(addressInfo.address, count, unitId);
                    break;
                case DISCRETE_INPUT:
                    readDiscreteInputs(addressInfo.address, count, unitId);
                    break;
                case INPUT_REGISTER:
                    readRegisters(addressInfo.address, count, unitId, true);
                    break;
                case HOLDING_REGISTER:
                    readRegisters(addressInfo.address, count, unitId, false);
                    break;
                default:
                    if (dataListener != null) {
                        dataListener.onError("不支持的寄存器类型: " + addressInfo.type);
                    }
                    return false;
            }
            return true;
        } catch (Exception e) {
            Log.e(TAG, "读取地址失败: " + e.getMessage(), e);
            if (dataListener != null) {
                dataListener.onError("读取地址失败: " + e.getMessage());
            }
            return false;
        }
    }
    
    /**
     * 根据地址字符串写入数据
     * 支持格式：
     * - 线圈: 00001-09999
     * - 保持寄存器: 40001-49999
     * @param addressStr 地址字符串
     * @param value 写入值
     * @param unitId 设备单元ID
     * @return 是否写入成功
     */
    public boolean writeAddress(String addressStr, Object value, int unitId) {
        ModbusAddressInfo addressInfo = parseModbusAddress(addressStr);
        
        if (addressInfo == null) {
            if (dataListener != null) {
                dataListener.onError("无效的Modbus地址: " + addressStr);
            }
            return false;
        }
        
        try {
            switch (addressInfo.type) {
                case COIL:
                    boolean boolValue;
                    if (value instanceof Boolean) {
                        boolValue = (Boolean) value;
                    } else if (value instanceof String) {
                        String strValue = (String) value;
                        boolValue = "1".equals(strValue) || "true".equalsIgnoreCase(strValue) || "on".equalsIgnoreCase(strValue);
                    } else if (value instanceof Number) {
                        boolValue = ((Number) value).intValue() != 0;
                    } else {
                        if (dataListener != null) {
                            dataListener.onError("无效的线圈值类型: " + value.getClass().getName());
                        }
                        return false;
                    }
                    return writeSingleCoil(addressInfo.address, boolValue, unitId);
                
                case HOLDING_REGISTER:
                    int intValue;
                    if (value instanceof Number) {
                        intValue = ((Number) value).intValue();
                    } else if (value instanceof String) {
                        try {
                            intValue = Integer.parseInt((String) value);
                        } catch (NumberFormatException e) {
                            if (dataListener != null) {
                                dataListener.onError("无效的寄存器值: " + value);
                            }
                            return false;
                        }
                    } else {
                        if (dataListener != null) {
                            dataListener.onError("无效的寄存器值类型: " + value.getClass().getName());
                        }
                        return false;
                    }
                    return writeSingleRegister(addressInfo.address, intValue, unitId);
                
                default:
                    if (dataListener != null) {
                        dataListener.onError("不支持写入的寄存器类型: " + addressInfo.type);
                    }
                    return false;
            }
        } catch (Exception e) {
            Log.e(TAG, "写入地址失败: " + e.getMessage(), e);
            if (dataListener != null) {
                dataListener.onError("写入地址失败: " + e.getMessage());
            }
            return false;
        }
    }
    
    /**
     * Modbus寄存器类型
     */
    public enum ModbusRegisterType {
        COIL,               // 线圈
        DISCRETE_INPUT,     // 离散输入
        INPUT_REGISTER,     // 输入寄存器
        HOLDING_REGISTER    // 保持寄存器
    }
    
    /**
     * Modbus地址信息
     */
    public static class ModbusAddressInfo {
        public ModbusRegisterType type;  // 寄存器类型
        public int address;              // 协议地址（0-based）
        public String typeDescription;   // 类型描述
        
        public ModbusAddressInfo(ModbusRegisterType type, int address, String typeDescription) {
            this.type = type;
            this.address = address;
            this.typeDescription = typeDescription;
        }
    }
    
    /**
     * 解析Modbus地址
     * 支持格式：
     * - 线圈: 00001-09999
     * - 离散输入: 10001-19999
     * - 输入寄存器: 30001-39999
     * - 保持寄存器: 40001-49999
     * @param addressStr 地址字符串
     * @return 解析后的地址信息，解析失败返回null
     */
    public static ModbusAddressInfo parseModbusAddress(String addressStr) {
        if (addressStr == null || addressStr.isEmpty()) {
            return null;
        }
        
        try {
            int address = Integer.parseInt(addressStr);
            
            // 解析地址类型和偏移
            if (address >= COIL_START && address <= COIL_END) {
                // 线圈 (00001-09999)
                return new ModbusAddressInfo(ModbusRegisterType.COIL, address - COIL_START, "线圈");
            } else if (address >= DISCRETE_INPUT_START && address <= DISCRETE_INPUT_END) {
                // 离散输入 (10001-19999)
                return new ModbusAddressInfo(ModbusRegisterType.DISCRETE_INPUT, address - DISCRETE_INPUT_START, "离散输入");
            } else if (address >= INPUT_REGISTER_START && address <= INPUT_REGISTER_END) {
                // 输入寄存器 (30001-39999)
                return new ModbusAddressInfo(ModbusRegisterType.INPUT_REGISTER, address - INPUT_REGISTER_START, "输入寄存器");
            } else if (address >= HOLDING_REGISTER_START && address <= HOLDING_REGISTER_END) {
                // 保持寄存器 (40001-49999)
                return new ModbusAddressInfo(ModbusRegisterType.HOLDING_REGISTER, address - HOLDING_REGISTER_START, "保持寄存器");
            }
        } catch (NumberFormatException e) {
            Log.e(TAG, "解析Modbus地址失败: " + e.getMessage(), e);
        }
        
        return null;
    }
    
    /**
     * 获取底层的ModbusRtuClient实例
     * @return ModbusRtuClient实例
     */
    public ModbusRtuClient getModbusRtuClient() {
        return modbusRtuClient;
    }
} 